import 'dart:convert';
import 'dart:io';
import 'package:connectivity/connectivity.dart';
import 'package:dio/adapter.dart';
import 'package:dio/dio.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart' hide Response hide FormData;
import 'package:live_music/pages/login/login.dart';
import 'package:live_music/utils/log_utils.dart';
import 'package:live_music/utils/sp_utils.dart';
import 'package:package_info/package_info.dart';
import 'http_helper.dart';
import 'log_interceptor.dart';
export 'http_helper.dart';

class HttpUtils {
  static Dio _dio;
  //配置代理标识 false 不配置
  static bool isProxy = DevSitting.isProxy;
  //网络代理地址
  static String proxyIp = DevSitting.proxyIp;

  static Dio createInstance() {
    BaseOptions options = BaseOptions(
      responseType: ResponseType.json,
      baseUrl: HttpHelper.baseURL,
      headers: {},
      connectTimeout: 20000,
      receiveTimeout: 2 * 60 * 1000,
      sendTimeout: 2 * 60 * 1000,
    );
    _dio = new Dio(options);
    //当App运行在Release环境时，inProduction为true；
    // 当App运行在Debug和Profile环境时，inProduction为false。
    if (!kIsWeb) {
      bool inProduction = bool.fromEnvironment("dart.vm.product");

      // if (!inProduction) {
      //   _dio.interceptors.add(LogsInterceptors());
      //   debugFunction();
      // }
    }
    return _dio;
  }

  static getInstance() async {
    if (_dio == null) {
      _dio = createInstance();
    }
    return _dio;
  }

  static void debugFunction() {
    // 添加log
    _dio.interceptors.add(LogsInterceptors());
    //配置代理
    if (isProxy) {
      _setupPROXY();
    }
  }

  /// 配置代理
  static void _setupPROXY() {
    (_dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate =
        (HttpClient client) {
      client.findProxy = (uri) {
        return 'PROXY $proxyIp';
      };
      client.badCertificateCallback =
          (X509Certificate cert, String host, int port) {
        //忽略证书
        return true;
      };
    };
  }

  static Future request<T>(
      {@required String method,
      @required String url,
      dynamic data,
      Function success,
      Function fail,
      bool setToken = true}) async {
    try {
      //没有网络
      var connectivityResult = await (new Connectivity().checkConnectivity());
      if (connectivityResult == ConnectivityResult.none) {
        return Future.error(
            ResponseInfo.error(code: 1000, message: "网络异常，请检查你的网络"));
      }
      Dio _dio = getInstance();
      _dio.options.headers["content-type"] = "application/json";
      Response response = await _dio.request(url,
          data: data, options: Options(method: MethodValues[method]));
      dynamic responseData = response.data;
      if (responseData is Map<String, dynamic>) {
        Map<String, dynamic> responseMap = responseData;
        if (responseMap['retcode'] == 0) {
          return Future.value(responseMap);
        } else {
          return Future.error(responseMap);
        }
      }
    } catch (e, s) {
      //异常
      ResponseInfo error = errorController(e, s);
      return Future.error(errorController(e, s));
    }
  }

  static Future postRequest(
      {@required String url,
      Map<String, dynamic> data,
      Map<String, dynamic> jsonMap}) async {
    FormData form;
    Map<String, dynamic> paramsConfiger;
    try {
      //没有网络
      var connectivityResult = await (new Connectivity().checkConnectivity());
      if (connectivityResult == ConnectivityResult.none) {
        return Future.error(
            ResponseInfo.error(code: 1000, message: "网络异常，请检查你的网络"));
      }
      Dio _dio = await getInstance();
      _dio.options = await buildOptions(_dio.options);
      data = paramsConfig(data);
      Response response = await _dio.post(url, data: data ?? {});
      dynamic responseData = response.data;
      if (responseData is Map<String, dynamic>) {
        Map<String, dynamic> responseMap = responseData;
        if (responseMap['retcode'] == 0) {
          return Future.value(responseMap);
        } else {
          if (responseData['retcode'] == 100001) {
            Get.to(LoginPage());
          }
          return Future.error(responseMap);
        }
      }
    } catch (e, s) {
      //异常
      ResponseInfo error = errorController(e, s);
      Map<String, dynamic> responseMap = {'retcode': -1, 'retdesc': ''};
      responseMap['retcode'] = -1;
      responseMap['retdesc'] = error.message;
      return Future.error(responseMap);
    }
  }

  static Map<String, dynamic> paramsConfig(Map params) {
      Map<String, dynamic> mapParams = {"randomKey": "OQlRb3WW89yfycQb97Rrt1Ef2OprRyKp"};
    if (params != null) {
      for (String key in params.keys) {
        mapParams[key] = params[key];
      }
    }
    return mapParams;
  }

  static Future<BaseOptions> buildOptions(BaseOptions options) async {
    ///请求header的配置
    Map<String, dynamic> localuserLogin = await SPUtil.getObject('userLogin');
    if (localuserLogin != null) {
      options.headers['token'] = localuserLogin['token'];
      // Get.to(LoginPage());
    }
    return Future.value(options);
  }
    static Future getRequest(
      {@required String url,
      Map<String, dynamic> data,
      CancelToken cancelTag,
      bool setToken = true}) async {
    try {
      //没有网络
      var connectivityResult = await (new Connectivity().checkConnectivity());
      if (connectivityResult == ConnectivityResult.none) {
        return Future.error(
            ResponseInfo.error(code: 1000, message: "网络异常，请检查你的网络"));
      }
      Dio _dio = await  getInstance();
      _dio.options.headers["content-type"] = "application/json";
      Response response =
          await _dio.get(url, queryParameters: data, cancelToken: cancelTag);
      dynamic responseData = response.data;
      if (responseData is Map<String, dynamic>) {
        Map<String, dynamic> responseMap = responseData;
        if (responseMap['retcode'] == 0) {
          return Future.value(responseMap);
        } else {
          return Future.error(responseMap);
        }
      }
    } catch (e, s) {
      //异常
      ResponseInfo error = errorController(e, s);
      return Future.error(errorController(e, s));
    }
  }

  static Future downImage(
      {@required String url,
      Map<String, dynamic> data,
      CancelToken cancelTag,
      bool setToken = true}) async {
    try {
      //没有网络
      var connectivityResult = await (new Connectivity().checkConnectivity());
      if (connectivityResult == ConnectivityResult.none) {
        return Future.error(
            ResponseInfo.error(code: 1000, message: "网络异常，请检查你的网络"));
      }
      Dio _dio = await getInstance();
      Response response =
          await _dio.get(url,  options: Options(responseType: ResponseType.bytes));
          return Future.value( response);
    } catch (e, s) {
      //异常
      ResponseInfo error = errorController(e, s);
      return Future.error(errorController(e, s));
    }
  }
}

ResponseInfo errorController(e, StackTrace s) {
  ResponseInfo responseInfo = ResponseInfo();
  responseInfo.success = false;

  //网络处理错误
  if (e is DioError) {
    DioError dioError = e;
    switch (dioError.type) {
      case DioErrorType.connectTimeout:
        responseInfo.message = "连接超时";
        break;
      case DioErrorType.sendTimeout:
        responseInfo.message = "请求超时";
        break;
      case DioErrorType.receiveTimeout:
        responseInfo.message = "响应超时";
        break;
      case DioErrorType.response:
        // 响应错误
        responseInfo.message = "响应错误";
        break;
      case DioErrorType.cancel:
        // 取消操作
        responseInfo.message = "已取消";
        break;
      case DioErrorType.other:
        // 默认自定义其他异常
        responseInfo.message = "网络请求异常";
        break;
    }
  } else {
    //其他错误
    responseInfo.message = "未知错误";
  }
  responseInfo.success = false;
  return responseInfo;
}

class ResponseInfo {
  bool success;
  int code;
  String message;
  dynamic data;

  ResponseInfo(
      {this.success = true, this.code = 200, this.data, this.message = "请求成功"});

  ResponseInfo.error(
      {this.success = false, this.code = 201, this.message = "请求异常"});
}

enum Method { GET, POST, DELETE, PUT, PATCH, HEAD }
//使用：MethodValues[Method.POST]
const MethodValues = {
  Method.GET: "get",
  Method.POST: "post",
  Method.DELETE: "delete",
  Method.PUT: "put",
  Method.PATCH: "patch",
  Method.HEAD: "head",
};
